Don't allow aliases to override builtin commands
authorAlex Crichton <alex@alexcrichton.com>
Fri, 22 Jul 2016 17:58:25 +0000 (10:58 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Fri, 22 Jul 2016 17:58:25 +0000 (10:58 -0700)
Closes #2901

src/bin/cargo.rs
tests/cargo_alias_config.rs

index d29a3cbb06feb9b2b946cef7fdf1a38b6b6d4372..fcb1ae77eb56008f2676480ceedecf9a7396ba1c 100644 (file)
@@ -155,7 +155,7 @@ fn execute(flags: Flags, config: &Config) -> CliResult<Option<()>> {
         return Ok(None)
     }
 
-    let mut args = match &flags.arg_command[..] {
+    let args = match &flags.arg_command[..] {
         // For the commands `cargo` and `cargo help`, re-execute ourselves as
         // `cargo -h` so we can go through the normal process of printing the
         // help message.
@@ -196,18 +196,32 @@ fn execute(flags: Flags, config: &Config) -> CliResult<Option<()>> {
         }
     };
 
-    let alias_list = try!(aliased_command(&config, &args[1]));
-    if let Some(alias_command) = alias_list {
-        // Replace old command with new command and flags
-        let chain = args.iter().take(1)
-            .chain(alias_command.iter())
-            .chain(args.iter().skip(2))
-            .map(|s| s.to_string())
-            .collect();
-        args = chain;
+    if try_execute(&config, &args) {
+        return Ok(None)
     }
 
-    macro_rules! cmd{
+    let alias_list = try!(aliased_command(&config, &args[1]));
+    let args = match alias_list {
+        Some(alias_command) => {
+            let chain = args.iter().take(1)
+                .chain(alias_command.iter())
+                .chain(args.iter().skip(2))
+                .map(|s| s.to_string())
+                .collect::<Vec<_>>();
+            if try_execute(&config, &chain) {
+                return Ok(None)
+            } else {
+                chain
+            }
+        }
+        None => args,
+    };
+    try!(execute_subcommand(config, &args[1], &args));
+    Ok(None)
+}
+
+fn try_execute(config: &Config, args: &[String]) -> bool {
+    macro_rules! cmd {
         ($name:ident) => (if args[1] == stringify!($name).replace("_", "-") {
             config.shell().set_verbosity(Verbosity::Verbose);
             let r = cargo::call_main_without_stdin($name::execute, config,
@@ -215,13 +229,12 @@ fn execute(flags: Flags, config: &Config) -> CliResult<Option<()>> {
                                                    &args,
                                                    false);
             cargo::process_executed(r, &mut config.shell());
-            return Ok(None)
+            return true
         })
     }
     each_subcommand!(cmd);
 
-    try!(execute_subcommand(config, &args[1], &args));
-    Ok(None)
+    return false
 }
 
 fn aliased_command(config: &Config, command: &String) -> CargoResult<Option<Vec<String>>> {
index 52453a1deb4c6d1f0c17c8bedc33faf07ed96ce4..c0d2705e0027155591e742ed90ce1adad7738447 100644 (file)
@@ -101,3 +101,22 @@ fn alias_with_flags_config() {
                                      --emit=dep-info,link -L dependency=[..]")
                 );
 }
+
+#[test]
+fn cant_shadow_builtin() {
+    let p = project("foo")
+        .file("Cargo.toml", &basic_bin_manifest("foo"))
+        .file("src/main.rs", r#"
+            fn main() {
+         }"#)
+        .file(".cargo/config",r#"
+            [alias]
+            build = "fetch"
+         "#);;
+
+    assert_that(p.cargo_process("build"),
+                execs().with_status(0)
+                       .with_stderr("\
+[COMPILING] foo v0.5.0 ([..])
+"));
+}